package com.example.a13;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class A13Application {

    public static void main(String[] param) {
        Proxy proxy = new Proxy();
        Target target = new Target();
        proxy.setMethodInterceptor(new MethodInterceptor() {
            @Override
            public Object intercept(Object p, Method method, Object[] args,
                                    MethodProxy methodProxy) throws Throwable {
                System.out.println("before");

                // ⬇️调用目标方法(三种)
//                Object result = method.invoke(target, args); // ⬅️反射调用
//                Object result = methodProxy.invoke(target, args); // ⬅️非反射调用, 结合目标用
                Object result = methodProxy.invokeSuper(p, args);// // ⬅️非反射调用, 结合代理用

                return result;

            }
        });

        // ⬇️调用代理方法

        proxy.save();
        proxy.save(1);
        proxy.save(2L);

        /*
            小结: 和JDK动态代理原理差不多
                1. 回调的接口换了一下，InvocationHandler 改成了 MethodInterceptor
                2. methodProxy.invoke 是不反射调用，它会正常（间接）调用目标对象的方法（Spring 采用）
                3. methodProxy.invokeSuper 也是不反射调用，它会正常（间接）调用代理对象的方法，可以省略目标对象

            注意: 调用 Object 的方法, 后两种在 jdk >= 9 时都有问题, 需要 --add-opens java.base/java.lang=ALL-UNNAMED
         */
    }
}
